/*
 *文件作用: 声明对外类型和API
 */

#ifndef LEPTJSON_H__
#define LEPTJSON_H__

#include <stddef.h>

//=========================Start: 宏=====================
//是否为数字 0~9
#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9')

//是否为数字1~9
#define ISDIGIT1TO9(ch) (((ch) >= '1') && ((ch) <= '9'))

//是否是布尔值
#define ISBOOLEAN(value) ((value) == 1 || (value) == 0)

//节点是否为 Boolean 类型
#define ISBOOLEANTYPE(v) ((v)->type == LEPT_BOOLEAN)

//字符串是否为 "true"
#define ISTRUE(string) (strcmp((string), "true") == 0 ? 1 : 0)

//设置节点为 LEPT_NULL 类型
#define lept_set_null(v)                                                                                               \
    do {                                                                                                               \
        lept_free(v);                                                                                                  \
    } while (0)

//比较c和ch是否相等
#define EXPECT(context, ch)                                                                                            \
    do {                                                                                                               \
        assert(*(context)->json == (ch));                                                                              \
        *(context)->json++;                                                                                            \
    } while (0)

//初始化节点类型
#define lept_init(v)                                                                                                   \
    do {                                                                                                               \
        (v)->type = LEPT_NULL;                                                                                         \
    } while (0)
//==========================End: 宏=======================

//声明json的数据类型
typedef enum {
    LEPT_NULL = 0,  // null
    LEPT_BOOLEAN,   //合并 true 和 false 为布尔类型
    LEPT_NUMBER,    // number
    LEPT_STRING,    // string
    LEPT_ARRAY,     // array
    LEPT_OBJECT     // object
} lept_type;

//声明json树形数据结构的节点，用以保存解析json得到的数据
//对于value，在true, false, null 的基础上, 增加 number
typedef struct {
    lept_type type;  //节点的数据类型
    //由于节点不可能同时为 string 和 number，故可以设计为 union 节省内存空间
    union {
        struct {
            char* string;
            size_t length;
        } str;
        double number;  //存放浮点数字
        int boolean;    //存放布尔值
    } union_struct;
} lept_value;

/*
 *json语法基本格式:
 *      whitespace - value - whitespace
 */
enum {
    LEPT_PARSE_OK = 0,                //解析正确
    LEPT_PARSE_EXPECT_VALUE,          //只含有whitespace
    LEPT_PARSE_ROOT_NOT_SINGULAR,     // value之后的whitespace后跟有其他字符
    LEPT_PARSE_INVALID_VALUE,         //值不属于三种字面值
    LEPT_PARSE_NUMBER_TOO_BIG,        //数字太大
    LEPT_PARSE_MISS_QUOTATION_MARK,   //字符串 quotation mark 不完整
    LEPT_PARSE_INVALID_STRING_ESCAPE  //非法转义字符
};

// API 声明

int lept_parse(lept_value* v, const char* json);  //解析json字符串
lept_type lept_get_type(const lept_value* v);     //获取节点的类型

// boolean 相关接口
int lept_get_boolean(lept_value* v);                //获取布尔变量值
void lept_set_boolean(lept_value* v, int boolean);  //设置布尔变量值

// number 相关接口
double lept_get_number(const lept_value* v);  //获取节点中的数字
void lept_set_number(double num);

// string 相关接口
const char* lept_get_string(lept_value* v);                              //获取字符串
void lept_set_string(lept_value* v, const char* string, size_t length);  //动态获取内存空间并将字符串写入
void lept_get_string_length(lept_value* v);                              //获取字符串长度

#endif